
#include <cstdio>
#include <BFile>
#include <BFolder>
#include <BLibrary>
#include <BReadWrite>
#include "IGlobal.h"

using namespace BWE;

bool RenameExtAlias(BString& ext)
{
	auto it = app_extAlias.find(ext);
	if (it.valid())
	{
		ext = it.value();
		return true;
	}
	return false;
}

BWEAPI BReadWrite* BWE::FindReadWrite(const BString& extension)
{
	if (extension.empty())
		return 0;

	BString ext = extension;
	RenameExtAlias(ext);
	
	for (auto it = app_plugins.begin(); it != app_plugins.end(); ++it)
	{
		bplugin& plugin = *it;
		if (plugin.ext == ext)
		{
			return plugin.rw.ptr();
		}
	}

	BString pluginName(ext);
#ifdef BWE_DEBUG
	pluginName += 'd';
#endif
	pluginName += ".brw";

	BString pluginPath;
	for (int i = 0; i < app_pluginPaths.size(); i++)
	{
		BString fileName = app_pluginPaths[i];
		fileName << '/' << pluginName;
		if (BFile::Exist(fileName))
		{
			pluginPath = fileName;
			break;
		}
	}

	if (pluginPath.empty())
	{
		BString fileName("./brws/");
		fileName << pluginName;
		if (BFile::Exist(fileName))
			pluginPath = fileName;
	}

	if (pluginPath.empty())
	{
		BString fileName = app_libPath;
		fileName << "/brws/" << pluginName;
		if (BFile::Exist(fileName))
			pluginPath = fileName;
	}

	if (pluginPath.empty())
	{
		return 0;
	}

	BLibraryHolder lib = new BLibrary(pluginPath);
	if (!lib->load())
	{
		printf("Error : Can't load plugin %s.\n", pluginPath.cstr());
		return 0;
	}

	func_get get = (func_get)lib->get("get");
	if (!get)
	{
		printf("Error : Can't find interface [get] in plugin %s.\n", pluginPath.cstr());
		return 0;
	}

	BReadWrite* rw = get();
	if(rw == 0)
		return 0;

	bplugin plugin;
	plugin.rw = rw;
	plugin.lib = lib;
	plugin.ext = ext;
	app_plugins.append(plugin);
	return rw;
}

BWEAPI bool BWE::SetExtAlias(const BString& ext, const BString& alias)
{
	if (ext.empty())
		return false;
	if (alias.empty())
	{
		return app_extAlias.remove(ext);
	}
	app_extAlias[ext] = alias;
	return true;
}
BWEAPI bool BWE::GetExtAlias(const BString& ext, BString& alias)
{
	if (ext.empty())
		return false;
	auto it = app_extAlias.find(ext);
	if (it.valid())
	{
		alias = it.value();
		return true;
	}
	return false;
}

BWEAPI BObject* BWE::ReadFile(const BString& fileName)
{
	BString ext = fileName.ext();
	if (ext.empty())
	{
		printf("ReadFile Error : can't find plugin without extension.\n");
		return 0;
	}
	ext.lower();
	RenameExtAlias(ext);
	if (BReadWrite* rw = FindReadWrite(ext))
	{
		if (BObject* object = rw->load(fileName))
			return object;
		const BString& message = rw->message();
		printf("ReadFile Error : %s.\n", message.cstr());
		return 0;
	}
	printf("ReadFile Error : can't find plugin for %s.\n", ext.cstr());
	return 0;
}
BWEAPI bool BWE::ReadFile(const BString& fileName, BObject* object)
{
	BString ext = fileName.ext();
	if (ext.empty())
	{
		printf("ReadFile Error : can't find plugin without extension.\n");
		return 0;
	}
	ext.lower();
	RenameExtAlias(ext);
	if (BReadWrite* rw = FindReadWrite(ext))
	{
		if (rw->load(fileName, object))
			return true;
		const BString& message = rw->message();
		printf("ReadFile Error : %s.\n", message.cstr());
		return false;
	}
	printf("ReadFile Error : can't find plugin for %s.\n", ext.cstr());
	return false;
}
BWEAPI bool BWE::WriteFile(const BString& fileName, const BObject* object)
{
	BString ext = fileName.ext();
	if (ext.empty())
	{
		printf("WriteFile Error : can't find plugin without extension.\n");
		return 0;
	}
	ext.lower();
	RenameExtAlias(ext);
	if (BReadWrite* rw = FindReadWrite(ext))
	{
		if (rw->save(fileName, object))
			return true;
		const BString& message = rw->message();
		printf("WriteFile Error : error message : %s.\n", message.cstr());
		return false;
	}
	printf("WriteFile Error : can't find plugin for %s.\n", ext.cstr());
	return false;
}

